/**
 **************************************************************************************************************************
 * Class that will record and play rendering commands
 * Multiple command buffers may be filled at once, but the rendering must happen in serial
 * This is the interface overridden by Rendering Backends to take advantage of direct D3D11 command buffers
 **************************************************************************************************************************
 * @file RBRenderDevice.h
 **************************************************************************************************************************/

#pragma once

#ifdef  HEADER_MSG
#pragma HEADER_MSG(RBRenderDevice.h)
#endif


/**************************************************************************************************************************
 * Includes
 **************************************************************************************************************************/

/**************************************************************************************************************************
 * Forward declarations
 **************************************************************************************************************************/

#define VIRTUAL virtual
#define PURE = 0

/**************************************************************************************************************************
 * Classes
 **************************************************************************************************************************/
class RBRenderDevice
{
public:

    struct MappedBuffer
    {
        void  *pData;
        uint32 RowPitch;
        uint32 DepthPitch;
    };

    VIRTUAL void Allocate(uint32 commandBufferSize) PURE;
    
    VIRTUAL void Execute() PURE;

    // Begin / End commands
    VIRTUAL void Begin() PURE;
    VIRTUAL void End() PURE;

    // Clear functions
    VIRTUAL void ClearDepthStencil(RBResourceView* pView, uint32 uiFlags, float32 fDepth, uint8 ucStencil) PURE;
    VIRTUAL void ClearRenderTarget(RBResourceView*) PURE;
    VIRTUAL void ClearState() PURE;

    VIRTUAL void CopyResource(RBHardwareBuffer* pSrc, RBHardwareBuffer* pDst) PURE;

    // Input Assembly
    VIRTUAL void IASetIndexBuffer(RBIndexBuffer* pIndexBuffer) PURE;
    VIRTUAL void IASetInputLayout(RBVertexDeclaration* pVertexDecl) PURE;
    VIRTUAL void IASetPrimitiveTopology(RBGeometryPrimitiveType::EType ePT) PURE;
    VIRTUAL void IASetVertexBuffers(uint32 uiStart, uint32 uiCount, RBVertexBuffer* pVertexBuffers) PURE;

    // Draw calls
    VIRTUAL void DrawIndexed( uint32 uiIndexCount, uint32 uiStartIndexLocation, uint32 uiBaseVertexLocation) PURE;
    VIRTUAL void DrawIndexedInstanced( uint32 uiIndexCountPerInstance, uint32 uiInstanceCount, uint32 uiStartIndexLocation, 
                                       int32 iBaseVertexLocation, uint32 uiStartInstanceLocation ) PURE;

    // Vertex Stage
    VIRTUAL void VSSetConstantBuffers(uint32 uiStart, uint32 uiCount, const RBHardwareBuffer* ppBuffers) PURE;
    VIRTUAL void VSSetSamplers(uint32 uiStart, uint32 uiCount, const RBTextureSampler* ppSamplers) PURE;
    VIRTUAL void VSSetShader(RBVertexShader* pVertexShader, RBShaderInstance* pInstances, uint32 uiInstancesCount) PURE;
    VIRTUAL void VSSetShaderResources(uint32 uiStart, uint32 uiCount, const RBResourceView* ppResourceViews ) PURE;

    // Rasterizer Stage
    VIRTUAL void RSSetState(RBRasterizerState* pState ) PURE;
    VIRTUAL void RSSetViewports(uint32 uiCount, RBViewPort* pViewports) PURE;


    // Pixel Stage
    VIRTUAL void PSSetConstantBuffers(uint32 uiStart, uint32 uiCount, const RBHardwareBuffer* ppBuffers) PURE;
    VIRTUAL void PSSetSamplers(uint32 uiStart, uint32 uiCount, const RBTextureSampler* ppSamplers) PURE;
    VIRTUAL void PSSetShader(RBPixelShader* pPixelShader, RBShaderInstance* pInstances, uint32 uiInstancesCount) PURE;
    VIRTUAL void PSSetShaderResources(uint32 uiStart, uint32 uiCount, const RBResourceView* ppResourceViews ) PURE;

    // Shader Output
    VIRTUAL void SOSetTargets(uint32 uiCount, const RBHardwareBuffer* pTargets) PURE;

    // Mapping resources
    VIRTUAL bool Map(RBHardwareBuffer* pBuffer, uint32 uiMapType, bool bWait, MappedBuffer* pMappedBuffer) PURE;
    VIRTUAL void Unmap(RBHardwareBuffer* pBuffer) PURE;

};